#include "../log.hpp"
#include <chrono>

//同步日志器下的多线程/单线程
//异步日志器下的多线程/单线程

void bench(const std::string &logger_name, size_t thread_count, size_t msg_count, size_t msg_len)
{
    //1.获取日志器
    wu::Logger::ptr logger = wu::getLogger(logger_name);
    std::cout << "测试日志: " << msg_count << "条, 总大小: " << (msg_count*msg_len)/1024 << "KB\n";
    //2.组织指定长度的日志消息
    std::string msg(msg_len-1, 'A');//少一个字节为后面在字符后面添加换行
    //3.创建指定数量的线程
    std::vector<std::thread> threads;
    std::vector<double> cost_arry(thread_count);
    size_t msg_of_thr = msg_count / thread_count;//每个线程需要写入的日志数量
    for(int i = 0; i < thread_count; ++i)
    {
        threads.emplace_back([&, i](){
            //4.线程内部开始计时
            auto begin = std::chrono::high_resolution_clock::now();
            //5.开始循环写日志
            for(int j = 0; j < msg_of_thr; ++j)
            {
                logger->fatal("%s", msg.c_str());
            }
            //6.线程内部计时结束
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost = end - begin;
            cost_arry[i] = cost.count();
            std::cout << "\t线程" << i << "\t: 输出数量: " << msg_of_thr << ", 耗时:" << cost.count() << "s\n";
        });
    }
    for(int i = 0; i < thread_count; ++i)
    {
        threads[i].join();
    }
    //7.计算总耗时:线程中耗时最长的即是总耗时(线程并发运行)
    double max_cost = cost_arry[0];
    for(auto &e : cost_arry)
    {
        if(max_cost < e) max_cost = e;
    }

    size_t msg_per_sec = msg_count / max_cost;//每秒输出的日志数量
    size_t size_per_sec = msg_len*msg_count / (max_cost * 1024);//每秒输出的日志大小
    //8.进行打印
    std::cout << "\t总耗时:" << max_cost << std::endl;
    std::cout << "\t每秒输出的日志数量:" << msg_per_sec << "条" << std::endl;
    std::cout << "\t每秒输出的日志大小:" << size_per_sec << "KB" << std::endl;
}

void async_bench()
{
    std::string name = "async-logger";
    std::unique_ptr<wu::LoggerBuilder> build(new wu::GlobalLoggerBuilder());
    build->buildLoggerName(name);
    build->buildEnableUnSafeAsync();//开启非安全模式--将实际落地的时间排除在外
    build->buildFormatter("%m%n");
    build->buildSink<wu::FileSink>("./filelog/async.log");
    build->build();
    
    bench(name, 1, 1000000, 100);
}

int main()
{
    async_bench();
    return 0;
}